# -*- coding: utf-8 -*-
# from common.comm import transform_alabo2_roman_num
from common.comm import update_filenames
from common.verify_code import *
from common.comm import *
from common.writer import writer
from ddt.excel_ddt import conf
import pytest
import allure

from key_word.webKeys import Web


# 暂不传参运行
# if conf.run_status == 1:
#     getattr(conf.obj, 'open_browser')(conf.br)
#     conf.run_status = 0

conf_stort_idx = str(conf.story_idx).zfill(3)

@allure.feature(str(conf.feature_idx)+'. '+conf.feature)
class Test_Web:
    print("运行次数")
    def setup_module(module):
        print("运行次数2")
    # 前后置条件、超时处理是否需要
    u = True
    temp = True
    th = ''
    # def __init__(self):
    #     self.video_flag = False
    video_flag = False
    def video_record(self):
        from PIL import ImageGrab
        import numpy as np
        import cv2
        import datetime
        # video_flag = video_flag

        # global flag  # 停止标志位
        # flag = False
        """
        屏幕录制！
        :return:
        """
        self.name = datetime.datetime.now().strftime('%Y-%m-%d %H-%M-%S')  # 当前的时间
        # vid = cv2.VideoCapture('./2022-06-13 15-33-12.avi')
        # video_width = int(vid.get(3))
        # video_height = int(vid.get(4))
        p = ImageGrab.grab()  # 获得当前屏幕
        a, b = p.size  # 获得当前屏幕的大小
        print("开始录制")
        fourcc = cv2.VideoWriter_fourcc(*'XVID')  # 编码格式
        video = cv2.VideoWriter('%s.mp4v' % self.name, fourcc, 10, (a, b))  # 输出文件命名为test.mp4,帧率为16，可以自己设置
        while True:
            im = ImageGrab.grab()
            imm = cv2.cvtColor(np.array(im), cv2.COLOR_RGB2BGR)  # 转为opencv的BGR格式
            video.write(imm)
            if self.video_flag:
                print("录制结束！")
                break
        video.release()
        # allure.attach.file(source=f'./{name}.mp4v', name=self.til, attachment_type=allure.attachment_type.MP4, extension='.mp4')

    def on_press(self):
        """
        键盘监听事件！！！
        :param key:
        :return:
        """
        # print(key)
        # global video_flag
        # if key == keyboard.Key.esc:
        self.video_flag = True
        print("stop monitor！")
        return False  # 返回False，键盘监听结束！

    # @pytest.mark.skip("跳过")，暂不使用
    def skip_case(self):
        pytest.fail()
        # allure.dynamic.title(title)
        # print("是否进入跳过中")

        #
        # with allure.step(step):
        #     # writer = Writer()
        #     # writer.copy_open('../../lib/web-testingshop.xlsx', '../../lib/result-web-testingshop.xlsx')
        #     # # 获取所有shtte
        #     # sheets = writer.get_sheets()
        #     # writer.set_sheet(sheets[0])
        #     # # 在原格式上写入写入
        #     # writer.write(3, 7, 'will')
        #     # # 更改颜色写入
        #     # writer.write(1, 2, 'hello', color=2)
        #     # writer.save_close()
        #
        #     if 'assert' in key_word:
        #         status = self.run_step(func, params)
        #         if status is True:
        #             pass
        #         else:
        #             pass
        #
        #     else:
        #         self.run_step(func, params)
        # # 获取参数列表
        # params = params[:params.index('')]
        #
        # if params:
        #     status = func(*params)
        #     '''
        #     将断言的状态返回
        #     '''
        #     return status
        # else:
        #
        #     print('最终状态:')
        #     status = func()
        #     # print('最终状态:', status)
        #     return status

    # web自动化pytest测试类
    @allure.step
    def run_step(self, func, params):
        # 获取参数列表
        params = params[:params.index('')]
        for i in params:
            if '{{' in str(i) and '}}' in str(i):  # 当i是float时需要转成字符串
                print("是否金额")
                num = params.index(i)
                start = i.find('{{')
                end = i.find('}}')
                key = i[start+2:end]
                a = ''
                try:
                    a = str(key) + "(conf.obj.driver)"
                    # print('输出关键字{}和类型{}'.format(a, type(a)))
                    a = eval(a)
                    a = i.replace('{{', '').replace('}}', '').replace(str(key), str(a))  # 只替换关键字内容
                    # ivercode = func(*params)
                except Exception as e:
                    a = str(key) + "()"
                    a = eval(a)
                    a = i.replace('{{','').replace('}}','').replace(str(key), str(a))  # 只替换关键字内容
                    Web().log.info('输出变量错误或者是key无参数时{}'.format(e))
                # try:
                #
                #     # funcs = eval(funcs)
                #     # ivercode = func(*params)
                # except Exception as e:
                #     print('输出错误报告2{}'.format(e))

                params[num] = a




                # Logger().log().debug("操作描述：{}".format(value[6]))
                #
                # # sheet.cell(row, 9).value = "pass"
                # Logger().log().debug("func值为：{}".format(func))
                # sheet.cell(row + 1, 9, func)

        if params:
            status = func(*params)
            '''
            将断言的状态返回
            '''
            return status

        else:

            status = func()
            return status

    @allure.story(str(conf_stort_idx)+'. '+conf.story)
    @pytest.mark.parametrize("case_params", conf.cases)
    def test_case(self, case_params):
        self.title = case_params[1][1]
        # allure.dynamic.title(self.title)
        # allure.dynamic.title(case_params[0][1])
        # print(f"打印空行数流到test:{conf.null_row_num_before_assert}")
        # 执行用例
        # 对被一行用例步骤反射执行
        # Web().log.info('正在执行的用例数据', case_params)
        # if len(case_params[0][9]) > 1:
        #     allure.dynamic.title('{}(跳过)'.format(case_params[0][1]))
        # else:
        #     allure.dynamic.title(case_params[0][1])
        case_params.insert(0, conf.story_row)
        # Web().log.info("给每条用例添加模块后的数据:",case_params)注意，不能这样写
        Web().log.info("给每条用例添加模块后的数据:{}".format(case_params))
        # is_skip = True
        major_status = True
        sub_status = True
        for i in range(0, len(case_params)):
            case_params_len = len(case_params)
            line = case_params[i]

            if len(line[0])>1 or len(line[1])>1:
                if len(line[0]) > 1 or len(line[1]) > 1:
                    if len(line[0]) > 1:
                        if len(line[9]) > 1:
                            major_status = False
                            # conf.story = case_params[0][0]+'(跳过)'
                            continue
                        else:
                            major_status = True
                            continue
                    elif len(line[1]) > 1:
                        if len(line[9]) > 1:
                            sub_status = False
                            continue
                        else:
                            sub_status = True
                            continue
            if major_status is False:
                sub_status = False
                # # 分组信息，不用执行
                # # if len(line[0])>1 and len(line[9])>1:
                # #     break
                # print('打印出line[0]:{}'.format(line[0]))
                # try:
                #
                #     print('打印出line[9]:{}'.format(line[9]))
                #     if len(line[9])>1:
                #         is_skip = bool(1-is_skip)
                #         print('打印出最终的is_skip--{}--'.format(is_skip))
                #     else:
                #         is_skip = True
                #         continue
                # except Exception as e:
                #     print('报错{}'.format(e))

            # Web().log.info('该用例能否执行:{}'.format(sub_status))
            try:
                # if line[3] == 'open_browser':
                #      wk = WebUIKeys('CHR')
                # else:

                if sub_status is True:
                    allure.dynamic.title(case_params[1][1])
                    if self.u:
                        Web().log.info('正在执行用例:{}'.format(case_params[1][1]))
                        self.til = case_params[1][1]
                        self.u = False
                    if self.temp:  # 因为未改名，所以需要使用实例变量取到最新的值
                        '''
                        暂不录制
                        import threading
                        Test_Web.th = threading.Thread(target=self.video_record)
                        Test_Web.th.start()
                        '''

                        self.temp = False



                    func = getattr(conf.obj, line[3])


                        # func = getattr(wk, line[3])

                    with allure.step(line[2]):
                        Web().log.info('正在执行步骤:{}'.format(line[2]))
                        # writer = Writer()
                        # writer.copy_open('../../lib/web-testingshop.xlsx', '../../lib/result-web-testingshop.xlsx')
                        # # 获取所有shtte
                        # sheets = writer.get_sheets()
                        # writer.set_sheet(sheets[0])
                        # # 在原格式上写入写入
                        # writer.write(3, 7, 'will')
                        # # 更改颜色写入
                        # writer.write(1, 2, 'hello', color=2)
                        # writer.save_close()

                        if 'assert' in line[3]:

                            status = self.run_step(func, line[4:])

                            if status is True:
                                # writer = Writer()
                                # writer.copy_open('../lib/web-testingshop.xlsx', '../lib/result-web-testingshop.xlsx')
                                # # 获取所有shtte
                                # sheets = writer.get_sheets()
                                # writer.set_sheet(sheets[0])
                                writer.set_sheet(conf.sheet)
                                # print('打印出con.i--{}--'.format(conf.i))
                                # print(f"打印空行数啊:{conf.null_row_num_before_assert}")
                                # temp = []
                                # tempnew = []
                                # for u in conf.null_row_num_before_assert:
                                #     print(f"打印u的位置{u}")
                                #     print(f"打印assert的位置{conf.i[0]}")
                                #     # if u>conf.i[0]:
                                #     #     temp.append(u)
                                #     if u > conf.i[0] + tempnew_leng:
                                #         temp.append(u)
                                #     else:
                                #         tempnew.append(u)
                                # print(temp)
                                # temp = min(temp)
                                # tempnew_leng = len(tempnew)
                                # print(f"打印过滤后的最小值位置{temp}")
                                # leng = len(conf.null_row_num_before_assert)
                                # print("打印长度:", leng)
                                # print("打印出很好", conf.null_row_num_before_assert[0])
                                writer.row = conf.i[0]+conf.null_row_num_before_assert[0]
                                conf.null_row_num_before_assert.pop(0)
                                conf.i.pop(0)
                                writer.clo = 8
                                # 在原格式上写入写入
                                # writer.write(3, 7, 'will')
                                # 更改颜色写入
                                writer.write(writer.row, writer.clo, 'pass', color=3)
                                writer.save_close()
                                # row = value[1]+1
                                '''
                                row = o
                                pass_(sheet.cell, row, 9)
                                '''
                                # sheet.cell(row, 9).value = "pass"
                                # sheet.cell(row, 9).fill = PatternFill('solid',fgColor='66ff00')
                                # sheet.cell(row, 9).font = Font(bold=True)
                            else:
                                # print("打印出状态啊", status)


                                writer.set_sheet(conf.sheet)
                                # print(f"打印空行数:{conf.null_row_num_before_assert}")
                                writer.row = conf.i[0]+conf.null_row_num_before_assert[0]
                                conf.null_row_num_before_assert.pop(0)
                                conf.i.pop(0)
                                writer.clo = 8
                                writer.write(writer.row, writer.clo, 'fail', color=2)
                                writer.save_close()
                                # 注意，必须放最后，因为执行完后下面的代码不执行
                                # get_screenshot_as_png()为获取当前屏幕截图的二进制文件数据string
                                # get_screenshot_as_base64()  # 截取当前屏幕图片，用于html页面直接嵌入base64编码图片,均无参数
                                allure.attach(conf.obj.driver.get_screenshot_as_png(), "错误截图", allure.attachment_type.PNG)

                                # pytest.fail()
                                # import pytest
                                # pytest.assume(False)
                                # import pytest_check as check
                                # check.equal(1, 2, msg="check断言失败")
                                # pytest.fail()
                                # print("打印呀",i+1,case_params_len)
                                if i + 1 != case_params_len:
                                    # 解决当有多个断言而且前面断言失败写入位置问题
                                    # conf.null_row_num_before_assert.pop(0)
                                    # conf.i.pop(0)
                                    # 用例多断言失败而且能够继续运行
                                    # pytest.assume(False)


                                    try:
                                        temp = int(case_params_len - (i + 1))
                                        for x in range(0, temp):
                                            # conf.null_row_num_before_assert.pop(0)
                                            conf.null_row_num_before_assert.pop(0)
                                            conf.i.pop()
                                    except Exception as e:
                                        Web().log.info("多个断言时处理assert和空行发生错误，错误信息:{}".format(e))
                                        import traceback
                                        traceback.print_exc()
                                    else:
                                        pass

                                    pytest.fail()


                                    # raise Exception("Sorry, it's broken.")
                                else:# 因为pytest.assume()在步骤中不会报错而pytest.fail()会，但是会导致后面代码不执行
                                    pytest.fail()
                                # pytest.fail()
                                # else:
                                #     # pytest.assume(False)
                                #     # conf.obj.driver.find_element_by_xpath('')
                                #     # try:
                                #     #     self.skip_case()
                                #     # except Exception as e:
                                #     #     continue



                                # 用的pytest - check断言，功能一样的
                                # pytest.assume(1 == 2)#建议使用这个，支持多重断言pip3 install pytest-assume
                                # from pytest import assume
                                # # 使用上下文管理器的好处是不用显示去try和finally捕获异常，建议使用这种写法，简洁有效。
                                # with assume:
                                #     # 只有第一个断言会被执行！
                                #     assert x == y



                        else:

                            self.run_step(func, line[4:])


                else:

                    if Test_Web.u:
                        Web().log.info('正在跳过用例:{}'.format(case_params[1][1]))
                        Test_Web.u = False
                    allure.dynamic.title(case_params[1][1]+'(跳过)')

                    with allure.step(line[2]):

                        if 'assert' in str(line[3]):
                            conf.null_row_num_before_assert.pop(0)
                            conf.i.pop(0)
                        else:
                            pass
                    if i+1 == case_params_len:
                        # 因为使用这个方法会导致函数内的代码不执行，无论是前面还是后面，所以需要先判断是否到用例的最后一行再执行该方法
                        pytest.skip()
                    # except Exception as e:
                    #     print("是否报错",e)
                    # else:
                    #     pass
                    # finally:
                    # try:

                    # except Exception as e:
                    #     print("hih",e)
                    # self.skip_case(case_params[1][1])



            except Exception as e:
                Web().log.error("运行用例过程中报错，报错信息:{}".format(e))
                import traceback
                traceback.print_exc()
                allure.attach(conf.obj.driver.get_screenshot_as_png(), "错误截图")
                pytest.fail()
        if line[3] == 'quit':
            # import keyboard
            # if keyboard.is_pressed('ENTER'):
            #  ActionChains(driver).key_down(Keys.CONTROL)\    .send_keys('c').key_up(Keys.CONTROL).perform()
            # conf.flag = True
            pass
        # elif is_skip is False:
        #     pass
        else:
            allure.attach(conf.obj.driver.get_screenshot_as_png(), "结果截图", allure.attachment_type.PNG)
            '''
            暂不录制
            print("修改文件名钱")
            update_filenames('./')
            print("修改文件名后")
            self.on_press()
            time.sleep(5)  # 注意，要录制结束才上传视频
            allure.attach.file(source=f'{self.name}.mp4', name=self.name, attachment_type=allure.attachment_type.MP4)
            '''

            '''
            目前视频无法观看，是否将其转换成二进制。参考https://www.pythonheidong.com/blog/article/277066/6e2b9d83154ba8da23c8/
            '''
            # with open(f'{self.name}.mp4',"rb") as f:
            #     allure.attach(f.read(), attachment_type=allure.attachment_type.MP4)
        # 执行完每条用例后，停止录制
        # self.on_press()
        # raise ValueError("invalid thread id")

if __name__ == '__main__':
    pytest.main(['-s', './test.py'])